package com.liyu.iblog.web;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.liyu.iblog.domain.Blog;
import com.liyu.iblog.domain.Comment;
import com.liyu.iblog.enums.ActiveTab;
import com.liyu.iblog.enums.PaginationType;
import com.liyu.iblog.service.BlogService;
import com.liyu.iblog.service.CommentService;

@Controller
@RequestMapping("/blogs")
public class BlogController {
    
    private static final Logger logger = LoggerFactory.getLogger(BlogController.class);
    
    private BlogService blogService;
    private CommentService commentService;
    
    @Autowired
    public BlogController(BlogService postService, CommentService commentService) {
        this.blogService = postService;
        this.commentService = commentService;
    }
    
    @RequestMapping(method = RequestMethod.GET)
    public String listBlogs(Model model) {
        logger.debug("handling list blogs request...");
        List<Blog> blogList = blogService.getBolgsWithTimeDescOrder(
                BlogService.BLOG_FIRST_RESULT_INDEX, BlogService.BLOG_PAGINATION_SIZE);
        model.addAttribute("blogs", blogList);
        //the request to "/blogs" point to the 1st page
        model.addAttribute("pageNum", 1);
        //if current page is full assume next page is available
        if (blogList != null && blogList.size() == BlogService.BLOG_PAGINATION_SIZE) {
            model.addAttribute("hasNextPage", true);
            model.addAttribute("nextPageNum", 2);
        }
        // tell view about the pagination style(page path style)
        model.addAttribute(PaginationType.PAGE_STYLE.toString(), true);
        // tell view about the selected tab
        model.addAttribute(ActiveTab.BLOG_TAB.toString(), true);
        
        return "blogs";
    }
    
    @RequestMapping(value = "/category/{categoryId}", method = RequestMethod.GET)
    public String listBlogsByCategory(
            @PathVariable String categoryId,
            @RequestParam(required = false) Integer pageNum,
            Model model) {
        
        if (pageNum == null || pageNum < 1)
            pageNum = 1;
   
        model.addAttribute("pageNum", pageNum);
        
        List<Blog> blogs = blogService.getBlogsByCategory(categoryId, 
                (pageNum - 1) * BlogService.BLOG_PAGINATION_SIZE, 
                BlogService.BLOG_PAGINATION_SIZE);
        model.addAttribute("blogs", blogs);
        
        if (pageNum > 1) {
            model.addAttribute("hasPrePage", true);
            model.addAttribute("prePageNum", pageNum - 1);
        }
        
        if (blogs != null && blogs.size() == BlogService.BLOG_PAGINATION_SIZE) {
            model.addAttribute("hasNextPage", true);
            model.addAttribute("nextPageNum", pageNum + 1);
        }
        
        model.addAttribute("categoryId", categoryId);
        model.addAttribute(PaginationType.CATEGORY_STYLE.toString(), true);
        model.addAttribute(ActiveTab.BLOG_TAB.toString(), true);
        
        return "blogs";
    }
    
    @RequestMapping(value = "/tag/{tagId}", method = RequestMethod.GET)
    public String listBlogsByTag(
            @PathVariable String tagId,
            @RequestParam(required = false) Integer pageNum,
            Model model) {
    
        if (pageNum == null || pageNum < 1)
            pageNum = 1;
   
        model.addAttribute("pageNum", pageNum);
        
        List<Blog> blogs = blogService.getBlogsByTag(tagId, 
                (pageNum - 1) * BlogService.BLOG_PAGINATION_SIZE, 
                BlogService.BLOG_PAGINATION_SIZE);
        model.addAttribute("blogs", blogs);
        
        if (pageNum > 1) {
            model.addAttribute("hasPrePage", true);
            model.addAttribute("prePageNum", pageNum - 1);
        }
        
        if (blogs != null && blogs.size() == BlogService.BLOG_PAGINATION_SIZE) {
            model.addAttribute("hasNextPage", true);
            model.addAttribute("nextPageNum", pageNum + 1);
        }
        
        model.addAttribute("tagId", tagId);
        model.addAttribute(PaginationType.TAG_STYLE.toString(), true);
        model.addAttribute(ActiveTab.BLOG_TAB.toString(), true);
        
        return "blogs";
    }
    
    @RequestMapping(value = "/page/{pageNum}", method = RequestMethod.GET)
    public String listBlogsOfPage(
            @PathVariable("pageNum") int pageNum,
            Model model) {
        //if the page number less than 1, redirect the request to /blogs
        if (pageNum < 1) 
            pageNum = 1;
            
        logger.debug("show posts at page " + pageNum);
        List<Blog> blogs = blogService.getBolgsWithTimeDescOrder(
                (pageNum - 1) * BlogService.BLOG_PAGINATION_SIZE,
                BlogService.BLOG_PAGINATION_SIZE);
        model.addAttribute("blogs", blogs);
        model.addAttribute("pageNum", pageNum);
        
        if (pageNum > 1) {
            model.addAttribute("hasPrePage", true);
            model.addAttribute("prePageNum", pageNum - 1);
        }
        
        //if current page is full assume next page is available
        if (blogs != null && blogs.size() == BlogService.BLOG_PAGINATION_SIZE) {
            model.addAttribute("hasNextPage", true);
            model.addAttribute("nextPageNum", pageNum + 1);
        }
        
        model.addAttribute(PaginationType.PAGE_STYLE.toString(), true);
        model.addAttribute(ActiveTab.BLOG_TAB.toString(), true);
        
        return "blogs";
    }
    
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public String showBlog(@PathVariable("id") String id, Model model) {
        logger.debug("handling show blog <" + id + "> request");
        Blog blog = blogService.getBlogById(id);
//        Blog blog = blogService.getBlogWithComment(id);
        model.addAttribute("blog", blog);
//        List<Comment> commentList = blog.getComments();
//        model.addAttribute("comments", commentList);
        model.addAttribute(ActiveTab.BLOG_TAB.toString(), true);
        return "blog";
    }
    
    //must include the jakson jar in the class path
    @RequestMapping(value = "/{id}/comments", method = RequestMethod.POST)
    public @ResponseBody Comment createComment(
            @PathVariable("id") String id,
            @RequestBody Comment comment) {
        logger.debug("recieving ajax comment of blog <" + id + "> from :" + comment.getPublisherName());
        commentService.createCommentForBlog(id, comment);
        //prevent cycle reference
        comment.setBlog(null);
        comment.setKey(null);
        return comment;
    }
    
    @RequestMapping(value="/{id}/comments/get", method = RequestMethod.GET)
    public @ResponseBody List<Comment> getCommentsOfPost(
            @PathVariable("id") String id,
            @RequestBody String requestMsg) {
        logger.debug("receiving comments fetching ajax request : " + id);
        List<Comment> comments = commentService.getCommentsByBlogId(id);
        return comments;
    }

}
